﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace AttributesFramework.Mapper
{
    public class Attributes
    {
        public static AttributesFramework.Attributes.DBTableAttribute GetDBTableAttribute(Type p_ClassType)
        {
            lock (Statics.DBTableAttributesByType)
            {
                if (!Statics.DBTableAttributesByType.ContainsKey(p_ClassType))
                {
                    object[] _customAttributes = p_ClassType.GetCustomAttributes(typeof(AttributesFramework.Attributes.DBTableAttribute), false);

                    if (_customAttributes.Length > 0)
                    {
                        Statics.DBTableAttributesByType[p_ClassType] = _customAttributes[0] as AttributesFramework.Attributes.DBTableAttribute;
                    }
                    else
                    {
                        throw new Exceptions.DBTableAttributeException(p_ClassType);
                    }
                }
            }

            return Statics.DBTableAttributesByType[p_ClassType];
        }

        public static List<AttributesFramework.Attributes.DBColumnAttribute> GetDBColumnAttributes(Type p_ClassType)
        {
            lock (Statics.DBColumnAttributesByType)
            {
                if (!Statics.DBColumnAttributesByType.ContainsKey(p_ClassType))
                {
                    Statics.DBColumnAttributesByType[p_ClassType] = new List<AttributesFramework.Attributes.DBColumnAttribute>();

                    List<AttributesFramework.Attributes.DBColumnAttribute> _DBColumns = new List<AttributesFramework.Attributes.DBColumnAttribute>();

                    foreach (PropertyInfo _propertyInfo in p_ClassType.GetProperties())
                    {
                        object[] _customAttributes = _propertyInfo.GetCustomAttributes(typeof(AttributesFramework.Attributes.DBColumnAttribute), false);

                        if (_customAttributes.Length > 0)
                        {
                            AttributesFramework.Attributes.DBColumnAttribute _reflectedFieldAttribute = _customAttributes[0] as AttributesFramework.Attributes.DBColumnAttribute;

                            _reflectedFieldAttribute.PropertyName = _propertyInfo.Name;

                            _DBColumns.Add(_reflectedFieldAttribute);
                        }
                    }

                    Statics.DBColumnAttributesByType[p_ClassType] = _DBColumns;
                }
            }

            return Statics.DBColumnAttributesByType[p_ClassType];
        }

        public static List<AttributesFramework.Attributes.DBRelationAttribute> GetDBRelationAttributes(Type p_ClassType)
        {
            lock (Statics.DBRelationAttributesByType)
            {
                if (!Statics.DBRelationAttributesByType.ContainsKey(p_ClassType))
                {
                    Statics.DBRelationAttributesByType[p_ClassType] = new List<AttributesFramework.Attributes.DBRelationAttribute>();

                    List<AttributesFramework.Attributes.DBRelationAttribute> _DBRelations = new List<AttributesFramework.Attributes.DBRelationAttribute>();

                    foreach (PropertyInfo _propertyInfo in p_ClassType.GetProperties())
                    {
                        object[] _customAttributes = _propertyInfo.GetCustomAttributes(typeof(AttributesFramework.Attributes.DBRelationAttribute), false);

                        if (_customAttributes.Length > 0)
                        {
                            AttributesFramework.Attributes.DBRelationAttribute _reflectedFieldAttribute = _customAttributes[0] as AttributesFramework.Attributes.DBRelationAttribute;

                            _reflectedFieldAttribute.PropertyName = _propertyInfo.Name;

                            _DBRelations.Add(_reflectedFieldAttribute);
                        }
                    }

                    Statics.DBRelationAttributesByType[p_ClassType] = _DBRelations;
                }
            }

            return Statics.DBRelationAttributesByType[p_ClassType];
        }

        public static List<AttributesFramework.Attributes.DBColumnAttribute> GetDBColumnsPrimaryKeys(Type p_ClassType)
        {
            return GetDBColumnAttributes(p_ClassType).FindAll(delegate(AttributesFramework.Attributes.DBColumnAttribute p_Attribute) { return p_Attribute.isPrimaryKey; });
        }

        public static List<AttributesFramework.Attributes.DBRelationAttribute> GetDBRelations(Type p_ClassType, AttributesFramework.Attributes.DBRelationType p_RelationType)
        {
            return GetDBRelationAttributes(p_ClassType).FindAll(delegate(AttributesFramework.Attributes.DBRelationAttribute p_Attribute) { return p_Attribute.RelationType == p_RelationType; });
        }

        public static List<AttributesFramework.Attributes.DBRelationAttribute> GetDBRelationsPrimaryKeys(Type p_ClassType)
        {
            return GetDBRelations(p_ClassType, AttributesFramework.Attributes.DBRelationType.ONE_ONE).FindAll(delegate(AttributesFramework.Attributes.DBRelationAttribute p_Attribute) { return p_Attribute.isPrimaryKey; });
        }
    }
}
